package com.jgp.sys.query;

import com.jgp.common.utils.JGPUtil;
import com.jgp.common.utils.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 项目   jgp
 * 作者   loufei
 * 时间   2017/8/15
 */
@Slf4j
public enum Operator {
    
    /**
     * 等于
     */
    eq(" ={} "),
    
    /**
     * 不等于
     */
    ne(" !={} "),
    
    /**
     * 大于
     */
    gt(" >{} "),
    
    /**
     * 小于
     */
    lt(" <{} "),
    
    /**
     * 大于等于
     */
    ge(" >={} "),
    
    /**
     * 小于等于
     */
    le(" <={} "),
    
    /**
     * 类似
     */
    like(" like '%{}%' "),
    
    
    /**
     * 类似
     */
    likeL(" like '%{}' "),
    
    /**
     * 类似
     */
    likeR(" like '{}%' "),
    
    /**
     * 包含
     */
    in(" in{} "), nin(" not in{} "),
    
    /**
     * 为Null
     */
    isn(" is null "),
    
    /**
     * 不为Null
     */
    isnn(" is not null "),
    
    between(" between {0},{1} ");
    
    private String symbol;
    
    Operator(String symbol) {
        this.symbol = symbol;
    }
    
    public String getSymbol() {
        return symbol;
    }
    
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    
    public String toSql(Object... value) {
        String sql = this.symbol;
        if (this.symbol.contains("{0},{1}") && value.length == 2) {
            sql = sql.replaceAll("\\{".concat("0").concat("\\}"), value(value[0]));
            sql = sql.replaceAll("\\{".concat("1").concat("\\}"), value(value[1]));
        } else if (value.length == 1) {
            sql = sql.replaceAll("\\{".concat("\\}"), value(value[0]));
        }
        return sql;
    }
    
    private String value(Object value) {
        String result = castToSqlValue(value);
        Class clazz = value.getClass();
        if (this.equals(eq) || this.equals(ne) || this.equals(gt) || this.equals(ge) || this.equals(lt) || this.equals(le)) {
            if (String.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz) || Timestamp.class
                    .isAssignableFrom(clazz) || LocalTime.class.isAssignableFrom(clazz) || LocalDateTime.class
                    .isAssignableFrom(clazz) || LocalDate.class.isAssignableFrom(clazz) || Enum.class.isAssignableFrom(clazz)) {
                return "'" + result + "'";
            }
        }
        return result;
    }
    
    
    private String castToSqlValue(Object value) throws RuntimeException {
        if (null == value) return null;
        Class clazz = value.getClass();
        try {
            if (String.class.isAssignableFrom(clazz)) {
                return value.toString();
            } else if (ReflectUtil.isBaseClass(clazz) || BigDecimal.class.isAssignableFrom(clazz)) {
                return String.valueOf(value);
            } else if (Date.class.isAssignableFrom(clazz) || Timestamp.class.isAssignableFrom(clazz)) {
                return JGPUtil.S_DATE_TIME_FORMATTER.format(value);
            } else if (LocalDate.class.isAssignableFrom(clazz)) {
                return JGPUtil.DATE_FORMATTER.format((LocalDate) value);
            } else if (LocalDateTime.class.isAssignableFrom(clazz)) {
                return JGPUtil.DATE_TIME_FORMATTER.format((LocalDateTime) value);
            } else if (LocalTime.class.isAssignableFrom(clazz)) {
                return JGPUtil.TIME_FORMATTER.format((LocalTime) value);
            } else if (Enum.class.isAssignableFrom(clazz)) {
                return ((Enum) value).name();
            } else if (List.class.isAssignableFrom(clazz)) {
                if (String.class.isAssignableFrom(((List) value).get(0).getClass())) {
                    return "('" + StringUtils.join((List) value, "','") + "')";
                } else {
                    return "(" + StringUtils.join((List) value, ",") + ")";
                }
            } else if (Set.class.isAssignableFrom(clazz)) {
                if (String.class.isAssignableFrom(((Set) value).iterator().next().getClass())) {
                    return "('" + StringUtils.join((Set) value, "','") + "')";
                } else {
                    return "(" + StringUtils.join((Set) value, ",") + ")";
                }
            } else if (clazz.isArray()) {
                log.error("不支持数组结构！");
                return null;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("类型转换失败！", e);
            throw new RuntimeException(e);
        }
    }}
